Repository navigation
Conversation
The broker can stop delivering one device's messages while the shared session keeps working for the others. The health manager counted timeouts for the whole session and any successful response reset the count, so a working device hid a failing one and the session was never restarted (Python-roborock#1012). Subscribing to the topic again on the same connection does not help; only a new connection does. Track MQTT requests per device and restart the session when a device has 3 timeouts within 30 minutes. A single response in between doesn't reset the count, since a failing connection may still deliver some of them; the device counts as recovered after 3 responses in a row. Timeouts from several devices in a row still restart the session at once. A device that stays unreachable restarts the session less and less often: after 30 minutes, then 1, 2 and 4 hours, and at most every 6 hours until it responds again. Each health decision is logged at info level.
A restart requested by the health manager disconnects a session whose broker was reachable, so waiting for the backoff interval only kept every device on the session without MQTT for ten seconds. Reconnect at once after such a restart; connections lost for any other reason, and a failed first reconnect attempt, still wait for the backoff. Every new connection also clears the timeouts counted on the previous one.
Add an mqtt_health section to the diagnostics of V1 and A01 devices: when the device started failing, its last success and timeout, request counts and its last 10 health events, newest first. Session restarts are recorded on every device with their cause. B01 devices don't report their requests to the health manager yet, so they get no section.
The health management section described local connection recovery as the HealthManager and stated that A01/B01 devices don't need one. Split it into local connection recovery and MQTT health management, covering the restart conditions and pacing and the mqtt_health diagnostics.
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #1012.
Problem
All devices on an account share one MQTT session. On my account, the broker sometimes stops delivering a Saros 10R's (V1,
roborock.vacuum.a144) MQTT responses, while an F25 Ultra (A01,roborock.wdv.a194) on the same connection keeps working. TheHealthManagercounted timeouts for the whole session, and any successful response reset that count. The F25's responses hid the Saros's timeouts, so the session was never restarted. In Home Assistant the map is only available over MQTT, so it stopped updating for hours. Status, battery and commands kept working because they use the local connection.Changes
fix: restart the MQTT session when one device stops receiving messages. Timeouts are now tracked for each device.
fix: reconnect right away after a forced MQTT session restart.
feat: add MQTT health to device diagnostics. V1 and A01 diagnostics get an
mqtt_healthsection with:failing_since,last_successandlast_timeout;timeouts_started,session_restartwith itscause(this_device,other_deviceorseveral_devices), andrecovered.B01 channels don't report to the health manager yet, so they get no section.
docs: the health management section of
docs/DEVICES.mddescribed local connection recovery as theHealthManager. It said A01/B01 devices don't need one. I split it into local connection recovery and MQTT health management.Size: 13 files, +880/−45. About 600 of those lines are tests.
Testing
pre-commit run --all-files: ruff, mypy, codespell and the other hooks pass. Unit tests: 2292 passed. MQTT broker tests (-m mqtt_broker) against EMQX fromcompose.yaml: 11 passed.What we observed
These are observations from one account, not an explanation.
{"online": false}. It recovers by itself in a few minutes.We can't tell whether the broker stops forwarding our requests to the device or the device's replies to us. Requests are QoS 0, so nothing confirms delivery.
Results with this branch
What didn't work, or was dropped
GET_NETWORK_INFOevery 10 minutes for locally connected V1 devices). It found broken topics while the vacuum was idle, but that meant a restart every 3–4 hours that nobody needed. Without it, a broken topic is found by the next map requests and repaired within about 2 minutes.Considered and not done
Open questions